package scala.examples.tcpoly.parsing

trait Syntax {
  class Term
	case class Var(name: String) extends Term
	case class Abs(name: String, body: Term) extends Term
	case class App(fun: Term, arg: Term) extends Term
}
// TODO: expected sets name of parser, add debugging switch that traces execution based on name
object LambdaParser extends StringParsers with MoreCombinators with Syntax {
  def letter = acceptIf(_.isLetter) expected("letter")
  def digit = acceptIf(_.isDigit) expected("digit")
  def ws = rep1(accept(' ')) expected("whitespace")
  def wss[T](p: Parser[T]): Parser[T] = opt(ws) ~> p <~ opt(ws)
  def ident = rep1(letter, letter | digit) ^^ {_.mkString("")} expected("identifier")

  def term = chainl1(termSingle, ws ^^ const(App(_: Term, _: Term)))    
  def termSingle: Parser[Term] = 
    ( '\\' ~> wss(ident) ~ ('.' ~> wss(term)) ^^ {case (x, body) => Abs(x, body)  }
    | ident                     ^^ {case x => Var(x)} 
    )
    
 
  def main(args: Array[String]) = println((term <~ eoi)(args(0)))
  
  def const[U, T](c: T): U => T = {x: U => c}
}